#include "SCA830.h"
module SCA830LogicP
{
	provides interface SCA830Logic;
	provides interface Init;
	uses interface SCA830Spi;
	uses interface Timer<TMilli> as SecondByteDelay;
	uses interface Leds;
}
implementation
{
	uint8_t state = STATE_IDLE;
	uint8_t cntrl;
	
	uint8_t regData;
	uint16_t xData;
	uint16_t tempData;
	bool msbReaded;
	error_t regSuccess;
	
	task void SignalDone()
	{
		if(state == STATE_STARTING)
		{
			signal SCA830Logic.PowerOnDone(regSuccess);
		}
		else if(state == STATE_STOPPING)
		{
			signal SCA830Logic.PowerOffDone(regSuccess);
		}
		else if(state == STATE_RSTATUS)
		{
			signal SCA830Logic.GetStatusDone(regSuccess, regData);
		}
		else if(state == STATE_RINTERRUPT)
		{
			signal SCA830Logic.GetInterruptDone(regSuccess, regData);
		}
		else if(state == STATE_RCONTROL)
		{
			signal SCA830Logic.GetControlDone(regSuccess, regData);
		}
		else if(state == STATE_SCONTROL)
		{
			signal SCA830Logic.SetControlDone(regSuccess);
		}
		else if(state == STATE_RX)
		{
			
			if (regSuccess != SUCCESS) xData = 0;
			signal SCA830Logic.GetXDone(regSuccess, xData);
		}
		else if(state == STATE_RTEMP)
		{
			if (regSuccess != SUCCESS) tempData = 0;
			signal SCA830Logic.GetTempDone(regSuccess, tempData);
		}
		
		if(state != STATE_STOPPING) state = STATE_IDLE;
		else state = STATE_OFF;
	}

	command error_t Init.init()
	{
		return SUCCESS;
	}

	command error_t SCA830Logic.PowerOn()
	{
		if(state == STATE_OFF)
		{
			state = STATE_STARTING;
			
			return call SCA830Spi.SetRegister(SCA_REG_CTRL, SCA_CMD_PUP);
		}
		else return FAIL;
	}

	command error_t SCA830Logic.PowerOff()
	{
		
		if(state == STATE_IDLE)
		{
			state = STATE_STOPPING;
			return call SCA830Spi.SetRegister(SCA_REG_CTRL, SCA_CMD_PDOWN);
		}
		else return FAIL;
	}

	command error_t SCA830Logic.Reset()
	{
		return FAIL;
	}

	command error_t SCA830Logic.GetStatus()
	{
		if(state == STATE_IDLE)
		{
			state = STATE_RSTATUS;
			return call SCA830Spi.GetRegister(SCA_REG_STATUS);
		}
		else return FAIL;
	}

	command error_t SCA830Logic.GetInterrupt()
	{
		if(state == STATE_IDLE)
		{
			state = STATE_RINTERRUPT;
			return call SCA830Spi.GetRegister(SCA_REG_INT);
		}
		else return FAIL;
	}
	
	command error_t SCA830Logic.GetControl()
	{
		if(state == STATE_IDLE)
		{
			state = STATE_RCONTROL;
			return call SCA830Spi.GetRegister(SCA_REG_CTRL);
		}
		else return FAIL;
	}

	command error_t SCA830Logic.SetControl()
	{
		if(state == STATE_IDLE)
		{
			state = STATE_SCONTROL;
			return call SCA830Spi.GetRegister(SCA_REG_CTRL);
		}
		else return FAIL;
	}

	command error_t SCA830Logic.GetX()
	{
		if(state == STATE_IDLE)
		{
			state = STATE_RX;
			msbReaded = FALSE;
			return call SCA830Spi.GetRegister(SCA_REG_X_MSB);
		}
		else return FAIL;
	}

	command error_t SCA830Logic.GetTemp()
	{
		if(state == STATE_IDLE)
		{
			state = STATE_RTEMP;
			msbReaded = FALSE;
			return call SCA830Spi.GetRegister(SCA_REG_TEMP_MSB);
		}
		else return FAIL;
	}

	event void SCA830Spi.GetRegisterDone(error_t succes, sca_status_t status, uint8_t data)
	{
		if(state == STATE_RX)
		{
			if(succes == SUCCESS && ! status.frameError)
			{
				if(! msbReaded)
				{
					xData = 0;
					xData |= (uint16_t)data << 8;
					msbReaded = TRUE;
					
					call SecondByteDelay.startOneShot(1);
				}
				else
				{
					xData |= data;
					regSuccess = succes;
					post SignalDone();
				}
			}
			else
			{
				regSuccess = succes;
				xData = 0;
				post SignalDone();
			}
		}
		else if(state == STATE_RTEMP)
		{
			if(succes == SUCCESS && ! status.frameError)
			{
				if(! msbReaded)
				{
					tempData = 0;
					tempData |= (uint16_t)data << 8;
					msbReaded = TRUE;
					
					call SecondByteDelay.startOneShot(1);
				}
				else
				{
					tempData |= data;
					regSuccess = succes;
					post SignalDone();
				}
			}
			else
			{
				regSuccess = succes;
				tempData = 0;
				post SignalDone();
			}
		}
		else
		{
			regData = data;
			regSuccess = succes;
			post SignalDone();
		}
	}
	
	event void SecondByteDelay.fired()
	{
		if(state == STATE_RX)
		{
			regSuccess = call SCA830Spi.GetRegister(SCA_REG_X_LSB);
			if(regSuccess != SUCCESS)
			{
				post SignalDone();
			}
		}
		else if(state == STATE_RTEMP)
		{
			regSuccess = call SCA830Spi.GetRegister(SCA_REG_TEMP_LSB);
			if(regSuccess != SUCCESS)
			{
				post SignalDone();
			}
		}
	}

	event void SCA830Spi.SetRegisterDone(error_t success, sca_status_t status)
	{
		if(state == STATE_INITING)
		{
			state = STATE_OFF;
		}
		else
		{
			regSuccess = success;
			post SignalDone();
		}
	}
}